﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TweetRating
{
    public class InformeDelRating
    {
        public string grafico { get; private set; }
        public List<Tuple<ProgramaDeTV, List<IComentario>>> programasYComentarios { get; private set; }

        #region Constructor
        public InformeDelRating(DateTime fecha, Hora desde, Hora hasta, List<Intencion> intenciones, iComunicadorConFuenteDeComentarios unComunicador, IEstrategiasDeClasificacionDeComentarios unAnalizador)
        {
            programasYComentarios = new List<Tuple<ProgramaDeTV, List<IComentario>>>();
            List<ProgramaDeTV> losProgramasEmitidos;
            using (Persistidor unPersistidor = new Persistidor())
                losProgramasEmitidos = unPersistidor.solicitarProgramasDeTVEmitidosPorDiaYHorario(fecha.DayOfWeek, desde, hasta).FindAll(unPrograma => unPrograma.programacion.diaDeEmision == fecha.DayOfWeek && desde.hora <= unPrograma.programacion.horaDeInicio.hora && unPrograma.programacion.horaDeFinalizacion.hora <= hasta.hora);
            this.grafico = graficar(losProgramasEmitidos.Select(unPrograma => new MedicionDeRating(unPrograma, buscarRatingPorPrograma(unPrograma, fecha, desde, hasta, intenciones, unComunicador, unAnalizador))).ToList().FindAll(unaMedicion => unaMedicion.rating > 0));
        }
        #endregion

        #region Auxiliares
        private int buscarRatingPorPrograma(ProgramaDeTV unPrograma, DateTime fecha, Hora desde, Hora hasta, List<Intencion> intencionesBuscadas, iComunicadorConFuenteDeComentarios unComunicador, IEstrategiasDeClasificacionDeComentarios unAnalizador)
        {
            List<IComentario> comentariosDelPrograma = new List<IComentario>();
            unPrograma.palabrasClave.ForEach(unaPalabra => unComunicador.solicitarComentarios(unaPalabra.obtenerPalabraClave(), obtenerFechaDeInicio(unPrograma, fecha, desde), obtenerFechaDeFinalizacion(unPrograma, fecha, hasta)).Select(unComentario => unAnalizador.analizar(unComentario)).ToList().FindAll(unComentario => intencionesBuscadas.Contains(unComentario.obtenerIntencion())).ForEach(unComentario => comentariosDelPrograma.Add(unComentario)));
            programasYComentarios.Add(new Tuple<ProgramaDeTV, List<IComentario>>(unPrograma, comentariosDelPrograma));
            return CalculadorDeRating.calcularRating(comentariosDelPrograma);
        }
        private DateTime obtenerFechaDeInicio(ProgramaDeTV unPrograma, DateTime fecha, Hora desde)
        {
            return new DateTime(fecha.Year, fecha.Month, fecha.Day, desde.hora, 0, 0);
        }
        private DateTime obtenerFechaDeFinalizacion(ProgramaDeTV unPrograma, DateTime fecha, Hora hasta)
        {
            return new DateTime(fecha.Year, fecha.Month, fecha.Day, hasta.hora, 0, 0);
        }
        private string graficar(List<MedicionDeRating> programasConRating)
        {
            Graficador unGraficador = new Graficador();
            if (programasConRating.Count > 0)
                return unGraficador.graficarRating(programasConRating);
            else
                return "";
        }
        #endregion
    }
}
